//Code inspired by Glenn Fowler's sudoku solver/generator
//The original is published under the following license
		/***********************************************************************
		*               This software is part of the ast package               *
		*          Copyright (c) 2005-2009 AT&T Intellectual Property          *
		*                      and is licensed under the                       *
		*                  Common Public License, Version 1.0                  *
		*                    by AT&T Intellectual Property                     *
		*                                                                      *
		*                A copy of the License is available at                 *
		*            http://www.opensource.org/licenses/cpl1.0.txt             *
		*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
		*                                                                      *
		*              Information and Software Systems Research               *
		*                            AT&T Research                             *
		*                           Florham Park NJ                            *
		*                                                                      *
		*                 Glenn Fowler <gsf@research.att.com>                  *
		***********************************************************************/
//This is a MODIFIED version of the original code 
// dedicated to band1 minlex only, no column swap
#include "cantables.h"
#include <fstream>
#include <iostream>
#include <stdio.h>
using namespace std;

// static Canon_t* 

Canon_t				test,best;

//void GenOut(Canon_t	& ca , unsigned char * inb ){
//	char 	 out[28], *s=out;
//	for (int i = 0; i < 3; i++)
//		for (int j = 0; j < 9; j++)
//			*s++ = ca.map[inb[tswap[ca.box][ca.row[i]][ca.col[j]]]] + '0';
//	out[27]=0;  
//	cout << out;
//}

void  canon3(unsigned char* sol){
	register int b, d, i, j, k, l, v;
	int		 pr,pc;
	byte *tc=test.col,* tr=test.row,*br=best.row,*bc=best.col,*tmap=test.map,*bmap=best.map;
	// initialize the worst canonical candidate 
	best=BestInit;
	/* search over all boxes */
	for (b = 0; b < 3; b++) {
		for (pr = 0; pr < 6; pr++)
			for (pc = 0; pc < 6; pc++) {
				//if(b==0 && pr==2 && pc==0) diag=1;
				test=TestInit;
				test.box = b;
				/* initialize the map to perm and lock 5 first digits 3 + 2*/
				for (i = 0; i < 3; i++) {
					tr[i] = tperm[pr][i];
					tc[i] = tperm[pc][i];
				}
				const unsigned char * sw0=tswap[b][tr[0]],
					                * sw1=tswap[b][tr[1]],
									* sw2=tswap[b][tr[2]],
									* bw1=tswap[best.box][br[1]],
									* bw2=tswap[best.box][br[2]];
				tmap[ sol [sw0 [ tc[0]] ] ] = 1;
				tmap[ sol [sw0 [ tc[1]] ] ] = 2;
				tmap[ sol [sw0 [ tc[2]] ] ] = 3;
				tmap[ sol [sw1 [ tc[0]] ] ] = 4;
				tmap[ sol [sw1 [ tc[1]] ] ] = 5;				
				k = 0; // map value 6 and order cols 4&5&6 
				for (i = 3; i < 9; i++) {
					if (tmap[sol[sw0 [i]]] == 4) { // find box 2 fitting with locked digits
						l = tboxOffset[i];
						for (j = 0; j < 3; j++)
							switch (tmap[sol[sw0 [j+l]]]) {
							case 4:	tc[3] = j+l;	k |= 01;	break;
							case 5:	tc[4] = j+l;	k |= 02;	break;
							case 0:
								tmap[ sol [sw0[ tc[5]=j+l ] ] ] = 6;
													k |= 04;		break;
						}
						break;
					}
				}
				if (k != 7)		goto next; // box 2 does not fit
				/* map values 7&8&9  from row 1 */
				for (j = 2; j < 6; j++) {
					if (!tmap[sol[sw1[tc[j]]]])  // filter box 3
						tmap[sol[sw1[tc[j]]]] = k++;
				}
		/* check row 2 cols 3&4&5&6 */
				for (j = 2; j < 6; j++) {
					if ((d = (int)tmap[sol[sw1[tc[j]]]]
					       - (int)bmap[sol[bw1[bc[j]]]])) {
						if (d > 0)			goto next;
						break;
					}
				}
				/* order cols 7&8&9 */
				j = (l == 3) ? 6 : 3;		k = j+1; 	l = j+2;
				if (tmap[sol[sw0[j]]]   > tmap[sol[sw0[k]]]) {
					v = j; j = k; k = v;
				}
				if (tmap[sol[sw0[j]]] 	> tmap[sol[sw0[l]]]) {
					v = j; j = l; l = v;
				}
				if (tmap[sol[sw0[k]]]   > tmap[sol[sw0[l]]]) {
					v = k; k = l; l = v;
				}
				tc[6] = j;		tc[7] = k;	tc[8] = l;
				if(d) goto smaller; // already smaller				
				for (j = 6; j < 9; j++) {// check row 2 cols 7&8&9 
					if ((d = (int)tmap[sol[sw1[tc[j]]]] 
					       - (int)bmap[sol[bw1[bc[j]]]])) 
						if (d > 0)	goto next; else goto smaller;						
				}
				for (j = 0; j < 9; j++) {// check row 3 
					if ((d = (int)tmap[sol[sw2[tc[j]]]] 
					       - (int)bmap[sol[bw2[bc[j]]]])) 
						if (d > 0)	goto next; else goto smaller;
				}
				if(!d) goto next; // forget auto morph count
smaller:		best = test;
next:	;// empty next
			}
	}
}

void rowminlex3(char *in, char *out) {// string in string out
	byte inb[27];
	for(int i=0;i<27;i++) {
		inb[i]=(in[i] & 15); // skip to int mode 0 8
	}
	canon3((unsigned char*)inb);
	register int	i,j;
	register char*	s = out;
	for (i = 0; i < 3; i++)
		for (j = 0; j < 9; j++)
			*s++ = best.map[inb[tswap[best.box][best.row[i]][best.col[j]]]] + '0';
	out[27]=0; // normally set by the calling program
}
